/****************************************************************

this file is part of Music Practice Audio Player

Copyright (C)2012 Serhii Ratsyborynskyi (ratz@live.ru)

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

******************************************************************/

#ifndef WAVFILE_HPP
#define WAVFILE_HPP



#include <QString>
#include <QtMultimedia/QAudioFormat>
#include <qfile.h>
#include "Interfaces/IAudio.hpp"

namespace AudioCore
{


/**
 * @brief
 * This class provides access to WAV PCM file.
 *
 */
class QWavFile : public IAudio
{
    Q_OBJECT

public:
/**
 * @brief
 * Default contructor.
 *
 * @param parent
 * parent QT object, or 0 should be passed. Implementation of QTObject interface.
 *
 */
    explicit QWavFile( QString path, QObject *parent=0 );

    virtual ~QWavFile();

protected:
    /**
     * @brief
     * Implementation of QIODevice interface.
     * @param data - pointer to data array
     * @param maxlen - data len to read
     * @return qint64 - real amound of read data
     * Refer to QIODevice class for more details
     */
    virtual qint64 readData(char *data, qint64 maxlen);
    /**
     * @brief
     * Implementation of QIODevice interface.
     * @param data - pointer to data array
     * @param maxlen - data len to read
     * @return qint64 - real amound of read data
     * Refer to QIODevice class for more details
     */
    virtual qint64 writeData(const char *data, qint64 len);
    /**
     * @brief
     * Return availible remaining bytes.
     * @return qint64 amount of remaining bytes
     */
    virtual qint64 bytesAvailable() const;

    virtual bool open( OpenMode mode);

// wav file impl
public:
    // Public methods
    /**
     * @brief
     *
     * @return QAudioFormat
     */
    QAudioFormat getAudioFormat();

    virtual bool isReady();

    virtual QString getState();
    /**
     * @brief
     * Open file for reading
     * @return QAudioFormat
     */
    bool open();



private:

    /**
     * @brief
     *
     */

    struct WavHeader
    {
        char    ChunkId[4]; /**< 36 + SubChunk2Size, or more precisely:
                               4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
                               This is the size of the rest of the chunk
                               following this number.  This is the size of the
                               entire file in bytes minus 8 bytes for the
                               two fields not included in this count:
                               ChunkID and ChunkSize. */
        int     ChunkSize; /**< TODO */
        char    Format[4]; // "WAVE"  //8-11 /**< TODO */
        char    Subchunk1ID[4]; // "fmt " /**< TODO */
        int     Subchunk1Size; /**< TODO */
        short   AudioFormat; /**< TODO */
        short   NumChannells; /**< TODO */
        int     SampleRate; /**< TODO */
        int     ByteRate; /**< TODO */
        short   BlockAlign; /**< TODO */
        short   BitPerSample; /**< TODO */
        char    Subchunk2ID[4]; /**< TODO */
        int     SubChunk2Size; /**< TODO */
    };

    /**
     * @brief
     * Read header of the wav file and return audio format
     */
    bool readWaveHeader();


private:
    // Private members
    QFile        mWavFile;
    QAudioFormat mAudioFormat;
    bool mbDataState;
    const static int wav_header_length = 44;
    bool isOpen;


    // Wav header
/*

4         4   ChunkSize
8         4   Format           Contains the letters "WAVE"
                               (0x57415645 big-endian form).

The "WAVE" format consists of two subchunks: "fmt " and "data":
The "fmt " subchunk describes the sound data's format:

12        4   Subchunk1ID      Contains the letters "fmt "
                               (0x666d7420 big-endian form).
16        4   Subchunk1Size    16 for PCM.  This is the size of the
                               rest of the Subchunk which follows this number.
20        2   AudioFormat      PCM = 1 (i.e. Linear quantization)
                               Values other than 1 indicate some
                               form of compression.
22        2   NumChannels      Mono = 1, Stereo = 2, etc.
24        4   SampleRate       8000, 44100, etc.
28        4   ByteRate         == SampleRate * NumChannels * BitsPerSample/8
32        2   BlockAlign       == NumChannels * BitsPerSample/8
                               The number of bytes for one sample including
                               all channels. I wonder what happens when
                               this number isn't an integer?
34        2   BitsPerSample    8 bits = 8, 16 bits = 16, etc.

The "data" subchunk contains the size of the data and the actual sound:

36        4   Subchunk2ID      Contains the letters "data"
                               (0x64617461 big-endian form).
40        4   Subchunk2Size    == NumSamples * NumChannels * BitsPerSample/8
                               This is the number of bytes in the data.
                               You can also think of this as the size
                               of the read of the subchunk following this
                               number.
44        *   Data             The actual sound data.*/

};

}

#endif

